/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "单数值计算.h"

#include <basic_common_function.h>


#include "Context/数据转换.h"

#include "节点/计算/计算类JIT函数.h"
#include "节点/插座/通用插座.h"
#include "节点/socket_utils.h"
#include "节点/节点树.h"
#include "运算符.h"
#include "节点数据声明.h"



template<typename T1, typename T2, typename T3>
void f_一元计算(T1* outData, T2* inDataA, T3* inDataB, uint32 运算符) {
	switch (运算符) {
		case 0: (*outData) = (*inDataA) + (*inDataB); break;
		case 1: (*outData) = (*inDataA) - (*inDataB); break;
		case 2: (*outData) = (*inDataA) * (*inDataB); break;
		case 3: (*outData) = (*inDataA) / (*inDataB); break;
	}

}





template<typename T1, typename T2, typename F>
void f_计算(std::vector<T1>& outData, std::vector<T1>& dataA, std::vector<T2>& dataB, F vec_func) {
	uint64 num = dataA.size();

	outData.resize(num);
	T1* p_do = outData.data();
	T1* p_d1 = dataA.data();
	T2* p_d2 = dataB.data();



	if (dataB.size() >= num) {
		for (int64 i = 0; i < num; ++i) {
			p_do[i] = vec_func(p_d1[i], p_d2[i]);
		}
	}
	else {
		for (int64 i = 0; i < num; ++i) {
			p_do[i] = vec_func(p_d1[i], p_d2[0]);
		}
	}
}






template<typename T1, typename T2>
void f_切换运算符(C_单值计算节点* node, T1* p_outData, T1* p_dataA, uint64 A_num, T2* p_dataB, uint64 B_num, E_运算符 运算符) {
	
	switch (运算符)
	{
	case E_运算符::e_逻辑_非: {
		f_一元计算<T1>(p_outData, p_dataA, A_num, 运算符);
		break;
	}
	default:
		break;
	}
}




C_单值计算节点::C_单值计算节点(S_设备环境& ctx) : C_节点基类(DEF_单值计算节点) {
	m_Ctx = ctx;
	f_setWName(u"计算");

	C_插座基类* socket;
	DEF_创建F32插座_I(u"源1", nullptr);
	DEF_创建F32插座_I(u"源2", nullptr);
	
	DEF_创建F32插座_O(u"out", nullptr);


	m_计算方式 = f_alloc_EnumProp(nullptr, {
			//	0			1			2			3		
			{u"+", u""}, {u"-", u""}, {u"*", u""}, {u"/", u""}, 
			//	4			5				5	
			{u"最大", u""}, {u"最小", u""}, //{u"sizeof", ""},
			//	6			7
			{u"%", u""}, //{u">>", ""}, 
		
		},
		u"计算方式",
		0,
		nullptr
	);
	m_计算方式.m_私有 = true;

	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU属性变量(m_计算方式);

}

C_单值计算节点::~C_单值计算节点() {
	f_prop_Release(m_计算方式);
}

#define _DEF_计算两向量标量节点_插座类型转换_                                                     \
创建数组 = socket1->f_get接入的数据类型() == E_值类型::e_Type_Vec3_1D ||                          \
                 socket2->f_get接入的数据类型() == E_值类型::e_Type_F32_1D;                       \
if (!创建数组 || (!socket1->f_isLink() && !socket2->f_isLink()) ) {                               \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3);           \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3);           \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);            \
	创建数组 = false;                                                                             \
}                                                                                                 \
else {                                                                                            \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3_1D);        \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3_1D);        \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);         \
	创建数组 = true;                                                                              \
}                                                                                                 \
socket1 = f_get输入插座(1);                                                                       \
socket2 = f_get输入插座(2);  

bool C_单值计算节点::f_update() {
	C_插座基类* inSocket1 = f_get输入插座(1);
	C_插座基类* inSocket2 = f_get输入插座(2);


	bool 创建数组 = false;
	switch (inSocket1->f_get接入的数据类型()) {
		case E_值类型::e_Type_I8_1D:
		case E_值类型::e_Type_I32_1D:
		case E_值类型::e_Type_UI32_1D:
		case E_值类型::e_Type_F32_1D:
			创建数组 = true;
			break;
	}
	switch (inSocket2->f_get接入的数据类型()) {
		case E_值类型::e_Type_I8_1D:
		case E_值类型::e_Type_I32_1D:
		case E_值类型::e_Type_UI32_1D:
		case E_值类型::e_Type_F32_1D:
			创建数组 = true;
			break;
	}

	if (!inSocket1->f_isLink() && !inSocket2->f_isLink()) {
		创建数组 = false;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
	}
	inSocket1 = f_get输入插座(1);
	inSocket2 = f_get输入插座(2);


	if (创建数组) {
		auto 数据1 = DEF_F32插座_1D数据(inSocket1, 0);
		auto 数据2 = DEF_F32插座_1D数据(inSocket2, 0);
		auto* outData = DEF_F32插座_1D数据(f_get输出插座(1));
		
		f_JIT_Fun_F32s_c_F32s(outData, 数据1, 数据2, f_prop_enum(m_计算方式));
	}
	else {
		
		auto 数据1 = DEF_F32插座数据(inSocket1, 0);
		auto 数据2 = DEF_F32插座数据(inSocket2, 0);
		E_运算符 方式 = E_运算符(f_prop_enum(m_计算方式));

		auto& outData = DEF_F32插座数据(f_get输出插座(1));
		outData = f_JIT_Fun_f_c_f(数据1, 数据2, f_prop_enum(m_计算方式));
	}

	return false;
}

std::string C_单值计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	bool 创建数组 = false;
	bool 创建浮点 = false;
	std::string name = f_getName();


	C_插座基类* inSocket1 = f_get输入插座(1);
	C_插座基类* inSocket2 = f_get输入插座(2);

	
	auto* rt = f_getThis节点树();
	switch (rt->m_树类型) {
		case E_节点树类型::e_type_几何着色节点树:
		case E_节点树类型::e_type_并行节点树:
		case E_节点树类型::e_type_着色节点树: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
			inSocket1 = f_get输入插座(1);
			inSocket2 = f_get输入插座(2);

			m_Code += inSocket1->f_构建变量代码(0);
			m_Code += inSocket2->f_构建变量代码(0);

			bool 浮点数 = false;
			switch (inSocket1->m_Type) {
				case E_值类型::e_Type_F32:
					if (inSocket1->m_GPU缓存.m_Buf) {
						f_buf_F32_at(inSocket1->m_GPU缓存) = DEF_F32插座数据(inSocket1);
					}
				case E_值类型::e_Type_F64:
					浮点数 = true;
					break;
			}

			switch (inSocket2->m_Type) {
				case E_值类型::e_Type_F32:
					if (inSocket2->m_GPU缓存.m_Buf) {
						f_buf_F32_at(inSocket2->m_GPU缓存) = DEF_F32插座数据(inSocket2);
					}
				case E_值类型::e_Type_F64:
					浮点数 = true;
					break;
			}

			((int32*)m_计算方式.m_GPU缓存[0].m_Buf->m_mappedPtr)[m_计算方式.m_GPU缓存[0].m_Mem.m_偏移] = f_prop_enum(m_计算方式);



			if (浮点数) {
				m_Code += "float " + name + " = 0;\n";
			}
			else {
				m_Code += "int " + name + " = 0;\n";
			}

			m_Code += "switch(" + f_代码构建_属性变量(m_计算方式, rt) + "){\n";

			m_Code += "case 0:\n";
			m_Code += name + " = " + inSocket1->f_getCode(0, false) + " + " + inSocket2->f_getCode(0, false) + ";\n";
			m_Code += "break;\n";

			m_Code += "case 1:\n";
			m_Code += name + " = " + inSocket1->f_getCode(0, false) + " - " + inSocket2->f_getCode(0, false) + ";\n";
			m_Code += "break;\n";

			m_Code += "case 2:\n";
			m_Code += name + " = " + inSocket1->f_getCode(0, false) + " * " + inSocket2->f_getCode(0, false) + ";\n";
			m_Code += "break;\n";

			m_Code += "case 3:\n";
			m_Code += name + " = " + inSocket1->f_getCode(0, false) + " / (" + inSocket2->f_getCode(0, false) + "+0.000000001);\n";
			m_Code += "break;\n";

			m_Code += "}\n";
			break;
		}
		default: {
			std::string 数量[2];

			if (!inSocket1->f_isLink()) {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
				inSocket1 = f_get输入插座(1);
			}
			if (!inSocket2->f_isLink()) {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
				inSocket2 = f_get输入插座(2);
			}
			
			auto 接入的数据类型1 = inSocket1->f_get接入的数据类型();
			auto 接入的数据类型2 = inSocket2->f_get接入的数据类型();

			switch (接入的数据类型1) {
				case E_值类型::e_Type_I8_1D:
				case E_值类型::e_Type_I32_1D:
				case E_值类型::e_Type_UI32_1D:
				case E_值类型::e_Type_F32_1D:
				case E_值类型::e_Type_Vec2_1D:
				case E_值类型::e_Type_Vec3_1D:
				case E_值类型::e_Type_Vec4_1D:
				case E_值类型::e_Type_iVec2_1D:
				case E_值类型::e_Type_iVec3_1D:
				case E_值类型::e_Type_iVec3_2D:
				case E_值类型::e_Type_uVec2_1D:
				case E_值类型::e_Type_uVec3_1D:
					创建数组 = true;
					break;
			}
			switch (接入的数据类型2) {
				case E_值类型::e_Type_I8_1D:
				case E_值类型::e_Type_I32_1D:
				case E_值类型::e_Type_UI32_1D:
				case E_值类型::e_Type_F32_1D:
				case E_值类型::e_Type_Vec2_1D:
				case E_值类型::e_Type_Vec3_1D:
				case E_值类型::e_Type_Vec4_1D:
				case E_值类型::e_Type_iVec2_1D:
				case E_值类型::e_Type_iVec3_1D:
				case E_值类型::e_Type_iVec3_2D:
				case E_值类型::e_Type_uVec2_1D:
				case E_值类型::e_Type_uVec3_1D:
					创建数组 = true;
					break;
				default:
					break;
			}

			


			if (创建数组) {
				if (f_代码构建_是否为单值浮点(接入的数据类型1) || f_代码构建_是否为单值浮点(接入的数据类型2)) {
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);

					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);

					创建浮点 = true;
				}
				else {
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32_1D);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32_1D);

					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32_1D);
				}
			}
			else {
				if (f_代码构建_是否为单值浮点(接入的数据类型1) || f_代码构建_是否为单值浮点(接入的数据类型2)) {
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);

					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);

					创建浮点 = true;
				}
				else {
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32);

					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32);
				}

			}
			inSocket1 = f_get输入插座(1);
			inSocket2 = f_get输入插座(2);

			std::string 运算类型代码 = f_代码构建_属性变量(m_计算方式, rt);

			if (创建数组) {
				if (创建浮点) {
					m_Code += "S_F32Array* " + name + ";\n";
				}
				else {
					m_Code += DEF_S(S_I32Array*)" " + name + ";\n";
				}

			}
			else {
				if (创建浮点) {
					m_Code += "float32 " + name + ";\n";
				}
				else {
					m_Code += "int32 " + name + ";\n";
				}
			}


			m_Code += "{\n";


			m_Code += inSocket1->f_构建变量代码(0);
			m_Code += inSocket2->f_构建变量代码(0);

			if (创建数组) {
				if (创建浮点) {
					m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "1") + ";\n";
					m_Code += DEF_S(f_JIT_Fun_F32s_c_F32s);
					m_Code += "(" + name + ", " + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ", " + 运算类型代码 + ");\n";
				}
				else {
					m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_I32_1D, "1") + ";\n";
					m_Code += DEF_S(f_JIT_单值数组计算);
					m_Code += "(" + name + ", " + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ", " + 运算类型代码 + ");\n";
				}
			}
			else {
				if (创建浮点) {
					m_Code += "auto& 参数A指针 = " + inSocket1->f_getCode(0) + ";\n";
					m_Code += "auto& 参数B指针 = " + inSocket2->f_getCode(0) + ";\n";
					m_Code += name + " = " + DEF_S(f_JIT_Fun_f_c_f)"(参数A指针, 参数B指针, " + 运算类型代码 + "); \n";
				}
				else {
					m_Code += "auto& 参数A指针 = " + inSocket1->f_getCode(0) + ";\n";
					m_Code += "auto& 参数B指针 = " + inSocket2->f_getCode(0) + ";\n";
					m_Code += name + " = " + DEF_S(f_JIT_单值整数计算)"(参数A指针, 参数B指针, " + 运算类型代码 + "); \n";
				}
			}

			m_Code += m_ReleaseCode;
			m_Code += "}\n";
			break;
		}
	}

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}

	return m_Code;
}

void C_单值计算节点::f_getStr(std::vector<std::vector<std::u16string>>& 文本) {
	auto* outSocket1 = f_get输出插座(1);

	switch (outSocket1->m_Type) {
	case E_值类型::e_Type_I32:
	case E_值类型::e_Type_UI32:
	case E_值类型::e_Type_F32:
	case E_值类型::e_Type_F64: {
		auto outData = DEF_F32插座数据(f_get输出插座(1));
		std::vector<std::u16string> 输入(2);
		输入[0] = f_getWName();
		输入[1] = f_浮点数值转宽字符串(outData);
		文本.push_back(输入);
		break;
	}

	case E_值类型::e_Type_I32_1D:
	case E_值类型::e_Type_UI32_1D:
	case E_值类型::e_Type_F32_1D: {
		auto outData = DEF_F32插座_1D数据(f_get输出插座(1));
		std::vector<std::u16string> 输入(1);
		输入[0] = f_getWName();

		for (uint32 i = 0; i < outData->count; ++i) {
			输入.push_back(f_浮点数值转宽字符串(outData->ptr_userData[i]));
		}
		文本.push_back(输入);
		break;
	}
	default:
		break;
	}
	
}

void C_单值计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_计算方式, f);
}

void C_单值计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_计算方式, f);
}

void C_单值计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	f_prop_enum(m_计算方式) = f_prop_enum(dynamic_cast<const C_单值计算节点*>(node)->m_计算方式);

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	socket1->f_Copy(node->f_get输入插座(1));
	socket2->f_Copy(node->f_get输入插座(2));
}

C_节点基类* f_node_创建单值计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单值计算节点(ctx);
}

C_节点基类* f_node_加载单值计算节点(S_设备环境& ctx, FILE* f){
	C_单值计算节点* node = new C_单值计算节点(ctx);
	return node;
}

void f_node_保存单值计算节点(C_节点基类* n, FILE* f) {
	C_单值计算节点* node = dynamic_cast<C_单值计算节点*>(n);
}



C_组合计算节点::C_组合计算节点(S_设备环境& ctx) : C_节点基类(DEF_单值计算节点) {
	m_Ctx = ctx;
	f_setWName(u"计算");

	C_插座基类* socket;
	DEF_创建F32插座_I(u"源1", nullptr);
	DEF_创建F32插座_O(u"out", nullptr);

	f_get输入插座(1)->f_set多输入();

	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			2			3		
		{u"+", u""}, {u"*", u""}, {u"|", u""}, {u"&", u""},
		//	4			5
		{u"^", u""}, {u"||", u""}, {u"&&", u""},

							  },
							  u"计算方式",
							  0,
							  nullptr
							  );
	m_计算方式.m_私有 = true;

	m_是否改变原数据 = f_alloc_BoolProp(nullptr, u"改变原数据");
	m_计算方式.m_私有 = true;

	f_构建代码_构建GPU插座变量(*f_get输入插座(1));
	f_构建代码_构建GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU属性变量(m_计算方式);
}

C_组合计算节点::~C_组合计算节点() {
	f_prop_Release(m_是否改变原数据);
	f_prop_Release(m_计算方式);
}

bool C_组合计算节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	uint32 链接数量 = socket1->f_getLinkNum();
	for (uint32 i = 0; i < 链接数量; ++i) {

	}
	return false;
}

std::string C_组合计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	bool 创建数组 = false;
	bool 创建浮点 = false;
	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	uint32 链接数量 = socket1->f_getLinkNum();

	
	for (uint32 i = 0; i < 链接数量; ++i) {
		auto 接入的数据类型1 = socket1->f_get接入的数据类型(i);

		if (f_代码构建_是否为数组(接入的数据类型1)) {
			创建数组 = true;
		}
		if (f_代码构建_是否为单值数组浮点(接入的数据类型1)) {
			创建浮点 = true;
		}
	}

	if (创建数组) {
		if (创建浮点) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);

			m_Code += DEF_S(S_F32Array*)" " + name + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "1") + ";\n";
		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32_1D);

			m_Code += DEF_S(S_I32Array*)" " + name + " = " + f_代码构建_创建Array(E_值类型::e_Type_I32_1D, "1") + ";\n";
		}
	}
	else {
		if (创建浮点) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);

			m_Code += DEF_S(float32)" " + name + ";\n";
		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32);

			m_Code += DEF_S(int32)" " + name + ";\n";
		}
	}
	socket1 = f_get输入插座(1);


	auto socketIn = socket1->f_get链接到的输出插座();
	for (uint32 i = 0; i < 链接数量; ++i) {
		socket1->f_getCode(0);
	}


	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_组合计算节点::f_getStr(std::vector<std::vector<std::wstring>>& 文本) {
}

void C_组合计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
	
		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_组合计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_组合计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	const C_组合计算节点* 组合计算节点 = dynamic_cast<const C_组合计算节点*>(node);
	if (组合计算节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(组合计算节点->m_计算方式);
		f_prop_enum(m_是否改变原数据) = f_prop_enum(组合计算节点->m_是否改变原数据);
	}
}

C_节点基类* f_node_创建组合计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单值计算节点(ctx);
}

C_节点基类* f_node_加载组合计算节点(S_设备环境& ctx, FILE* f) {
	C_单值计算节点* node = new C_单值计算节点(ctx);
	return node;
}

void f_node_保存组合计算节点(C_节点基类* n, FILE* f) {
	C_单值计算节点* node = dynamic_cast<C_单值计算节点*>(n);
}




C_位运算节点::C_位运算节点(S_设备环境& ctx) : C_节点基类(DEF_位运算节点) {
	m_Ctx = ctx;
	f_setWName(u"位运算");

	C_插座基类* socket;
	DEF_创建I32插座_I(u"a", nullptr);
	DEF_创建I32插座_I(u"b", nullptr);
	DEF_创建I32插座_O(u"c", nullptr);

	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			2			3		
		{u"|", u""}, {u"&", u""}, {u"^", u""}, {u"<<", u""}, {u">>", u""}, 

							  },
							  u"计算方式",
							  0,
							  nullptr
							  );
	m_计算方式.m_私有 = true;

	m_是否改变原数据 = f_alloc_BoolProp(nullptr, u"改变原数据");
	m_是否改变原数据.m_私有 = true;
	f_prop_Bool(m_是否改变原数据) = false;
}

C_位运算节点::~C_位运算节点() {
	f_prop_Release(m_是否改变原数据);
	f_prop_Release(m_计算方式);
}

bool C_位运算节点::f_update() {
	return false;
}

std::string C_位运算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	bool 创建数组 = false;
	bool 创建浮点 = false;
	std::string name = f_getName();


	auto* socket1 = f_get输入插座(1);
	uint32 链接数量 = socket1->f_getLinkNum();

	auto 接入的数据类型1 = socket1->f_get接入的数据类型(0);
	if (f_代码构建_是否为数组(接入的数据类型1)) {
		创建数组 = true;
	}
	if (f_代码构建_是否为单值数组浮点(接入的数据类型1)) {
		创建浮点 = true;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_UI32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32_1D);

		m_Code += DEF_S(S_UI32Array*)" " + name + " = " + f_代码构建_创建Array(E_值类型::e_Type_UI32_1D, "1") + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_UI32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32);

		m_Code += DEF_S(int32)" " + name + ";\n";
	}
	socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);
	auto 运算类型 = f_代码构建_属性变量(m_计算方式, f_getThis节点树());
	if (创建数组) {
		if (f_prop_Bool(m_是否改变原数据)) {
		}
		else {
			m_Code += DEF_S(f_JIT_位运算Um)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + name + ", " + 运算类型 + ");\n";
		}
	}
	else {
		if (f_prop_Bool(m_是否改变原数据)) {
			m_Code += DEF_S(f_JIT_位运算Uxx)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + 运算类型 + ");\n";
		}
		else {
			m_Code += name + " = " + DEF_S(f_JIT_位运算U)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + 运算类型 + ");\n";
		}
		
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	if (f_prop_Bool(m_是否改变原数据)) {
		f_get输出插座(1)->f_setCode(socket1->f_getCode(0));
	}
	else {
		f_get输出插座(1)->f_setCode(name);
	}
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			if (f_prop_Bool(m_是否改变原数据)) {
			
			}
			else {
				m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
			}
		}
		return "";
	}
	if (创建数组) {
		if (f_prop_Bool(m_是否改变原数据)) {
		}
		else {
			释放 += f_代码构建_销毁数组(name);
		}
	}
	return m_Code;
}

void C_位运算节点::f_getStr(std::vector<std::vector<std::wstring>>& 文本) {

}

void C_位运算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_0, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_是否改变原数据, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_位运算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);
	f_prop_Save(m_是否改变原数据, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_位运算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	const C_位运算节点* 组合计算节点 = dynamic_cast<const C_位运算节点*>(node);
	if (组合计算节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(组合计算节点->m_计算方式);
		f_prop_Bool(m_是否改变原数据) = f_prop_Bool(组合计算节点->m_是否改变原数据);
	}
}

C_节点基类* f_node_创建位运算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_位运算节点(ctx);
}

C_节点基类* f_node_加载位运算节点(S_设备环境& ctx, FILE* f) {
	C_位运算节点* node = new C_位运算节点(ctx);
	return node;
}

void f_node_保存位运算节点(C_节点基类* n, FILE* f) {
	C_位运算节点* node = dynamic_cast<C_位运算节点*>(n);
}






C_逻辑计算节点::C_逻辑计算节点(S_设备环境& ctx) : C_节点基类(DEF_逻辑计算节点) {
	m_Ctx = ctx;
	f_setWName(u"逻辑运算");

	C_插座基类* socket;
	DEF_创建F32插座_I(u"源1", 0);
	DEF_创建F32插座_I(u"源2", 0);

	DEF_创建I8插座_O(u"真", 0);
	//DEF_创建I8插座_O(u"假", 0);


	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			 2		      3		
		{u">", u""}, {u"<", u""},  {u">=", u""}, {u"<=", u""},
		
		//	4			5			 6			  7			  8				
		{u"==", u""}, {u"!=", u""}, {u"&&", u""}, {u"||", u""}, //{u"|", ""}, {u"&", ""}, {u"^", ""},
		
		},
		u"计算方式",
		0,
		nullptr
		);
	m_计算方式.m_私有 = true;
}

C_逻辑计算节点::~C_逻辑计算节点() {
	f_prop_Release(m_计算方式);
}

bool C_逻辑计算节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	auto 接入的数据类型1 = socket1->f_get接入的数据类型();
	auto 接入的数据类型2 = socket2->f_get接入的数据类型();

	if (!socket1->f_isLink()) 接入的数据类型1 = E_值类型::e_Type_F32;
	if (!socket2->f_isLink()) 接入的数据类型2 = E_值类型::e_Type_F32;
	
	bool 创建数组 = f_代码构建_是否为数组(接入的数据类型1) || f_代码构建_是否为数组(接入的数据类型2);
	
	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);

		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8_1D);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);

		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8);
	}
	socket1 = f_get输入插座(1);
	socket2 = f_get输入插座(2);


	auto 计算方式 = f_代码构建_属性变量(m_计算方式, f_getThis节点树());
	if (创建数组) {
		auto* outData = DEF_I8插座_1D数据(f_get输出插座(1));
		f_JIT_Fn_逻辑计算m(DEF_F32插座_1D数据(socket1), DEF_F32插座_1D数据(socket2), outData, f_prop_enum(m_计算方式));
	}
	else {
		int8 outData = 0;
		f_JIT_Fn_逻辑计算(DEF_F32插座数据(socket1), DEF_F32插座数据(socket2), outData, f_prop_enum(m_计算方式));

		f_get输出插座(1)->f_setData(&outData);
	}

	return false;
}

std::string C_逻辑计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();

	C_节点树* rt = f_getThis节点树();
	
	false;
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	auto 接入的数据类型1 = socket1->f_get接入的数据类型();
	auto 接入的数据类型2 = socket2->f_get接入的数据类型();


	if (!socket1->f_isLink()) {
		接入的数据类型1 = E_值类型::e_Type_F32;
	}
	if (!socket2->f_isLink()) {
		接入的数据类型2 = E_值类型::e_Type_F32;
	}

	bool 创建数组 = f_代码构建_是否为数组(接入的数据类型1) || f_代码构建_是否为数组(接入的数据类型2);
	bool 创建浮点 = f_代码构建_是否为单值浮点(接入的数据类型1) || f_代码构建_是否为单值浮点(接入的数据类型2);

	
	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);
		
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8_1D);

		m_Code += DEF_S(S_I8Array*)" " + name + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
		
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8);

		m_Code += DEF_S(int8)" " + name + ";\n";
	}
	socket1 = f_get输入插座(1);
	socket2 = f_get输入插座(2);


	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	auto s1Code = socket1->f_getCode(0);
	auto s2Code = socket2->f_getCode(0);

	if (s1Code.empty() || s2Code.empty()) {
		m_编译成功 = false;
	}

	auto 计算方式 = f_代码构建_属性变量(m_计算方式, f_getThis节点树());
	if (创建数组) {
		m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_I8_1D, "1");
		m_Code += DEF_S(f_JIT_Fn_逻辑计算m);
	}
	else {
		m_Code += DEF_S(f_JIT_Fn_逻辑计算);
	}
	m_Code += "(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + name + ", " + 计算方式 + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";
	

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;

		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_逻辑计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_1, S_引擎配置::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_逻辑计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);
	f_file_保存文件块(f, 文件块, 块);
}

void C_逻辑计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	const C_逻辑计算节点* 组合计算节点 = dynamic_cast<const C_逻辑计算节点*>(node);
	if (组合计算节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(组合计算节点->m_计算方式);
	}
}

C_节点基类* f_node_创建逻辑计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_逻辑计算节点(ctx);
}

C_节点基类* f_node_加载逻辑计算节点(S_设备环境& ctx, FILE* f) {
	C_逻辑计算节点* node = new C_逻辑计算节点(ctx);
	return node;
}

void f_node_保存逻辑计算节点(C_节点基类* n, FILE* f) {
	C_逻辑计算节点* node = dynamic_cast<C_逻辑计算节点*>(n);
}




C_单目计算节点::C_单目计算节点(S_设备环境& ctx) : C_节点基类(DEF_单目计算节点) {
	m_Ctx = ctx;
	f_setWName(u"单目运算");

	C_插座基类* socket;
	DEF_创建F32插座_I(u"源1", nullptr);
	DEF_创建F32插座_O(u"结果", nullptr);


	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1					
		{u"符号", u""}, {u"!", u""}, 
		//	2			3
		{u"++", u""}, {u"--", u""},
		{u"正负", u""}, //{u"", ""},
		},
		u"计算方式",
		0,
		nullptr
		);
	m_计算方式.m_私有 = true;

	f_构建代码_分配渲染器GPU属性变量(m_计算方式);
}

C_单目计算节点::~C_单目计算节点() {
	f_构建代码_释放渲染器GPU属性变量(m_计算方式);
	f_prop_Release(m_计算方式);
}

bool C_单目计算节点::f_update() {
	auto& v = DEF_F32插座数据(f_get输入插座(1));
	auto& r = DEF_F32插座数据(f_get输出插座(1));

	switch (f_prop_enum(m_计算方式)) {
	case 0:
		r = sign(v);
		break;

	case 1:
		r = !v;
		break;

	case 2:
		r += 1;
		break;

	case 3:
		r -= 1;
		break;
	default:
		break;
	}
	return false;
}

std::string C_单目计算节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();
	auto* rt = f_getThis节点树();
	bool 在着色器里 = rt->m_树类型 == E_节点树类型::e_type_着色节点树;

	bool 创建数组 = false;

	auto* socket1 = f_get输入插座(1);
	auto type = socket1->f_get接入的数据类型();

	switch (type) {
		case E_值类型::e_Type_I8_1D:
		case E_值类型::e_Type_I32_1D :
		case E_值类型::e_Type_UI32_1D:
		case E_值类型::e_Type_F32_1D:
			创建数组 = true;
			break;
		default:
			break;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);

		m_Code = DEF_S(S_F32Array*)" " + name + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);

		m_Code = DEF_S(float)" " + name + ";\n";
	}
	
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	if (创建数组) {
		m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "1");
		m_Code += DEF_S(f_JIT_Fn_单目计算m)"(" + socket1->f_getCode(0) + ", " + name + ", " + f_代码构建_属性变量(m_计算方式, f_getThis节点树()) + ");\n";
	}
	else {
		m_Code += "switch (" + f_代码构建_属性变量(m_计算方式, f_getThis节点树()) + ") {\n";
		m_Code += "case 0: " + name + " = " + DEF_S(sign)"(" + socket1->f_getCode(0) + "); break;\n";

		if (在着色器里) {
			m_Code += "case 1: " + name + " = float(!bool(" + socket1->f_getCode(0) + ")); break;\n";
		}
		else {
			m_Code += "case 1: " + name + " = float(!int(" + socket1->f_getCode(0) + ")); break;\n";
		}
		
		m_Code += "case 2: " + name + " = (" + socket1->f_getCode(0) + ") + 1; break;\n";
		m_Code += "case 3: " + name + " = (" + socket1->f_getCode(0) + ") - 1; break;\n";
		m_Code += "case 4: " + name + " = bool(" + socket1->f_getCode(0) + ") ? 1 : -1; break;\n";
		m_Code += "}\n";
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_单目计算节点::f_getStr(std::vector<std::vector<std::u16string>>& 文本) {
	auto& r = DEF_F32插座数据(f_get输出插座(1));
	std::vector<std::u16string> 输出(2);
	输出[0] = f_getWName();
	输出[1] = f_浮点数值转宽字符串(r);
	文本.push_back(输出);
}

void C_单目计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_单目计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_单目计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	f_prop_enum(m_计算方式) = f_prop_enum(dynamic_cast<const C_单目计算节点*>(node)->m_计算方式);
}

C_节点基类* f_node_创建单目计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单目计算节点(ctx);
}

C_节点基类* f_node_加载单目计算节点(S_设备环境& ctx, FILE* f) {
	C_单目计算节点* node = new C_单目计算节点(ctx);
	return node;
}

void f_node_保存单目计算节点(C_节点基类* n, FILE* f) {
	C_单目计算节点* node = dynamic_cast<C_单目计算节点*>(n);
}





C_累计计算节点::C_累计计算节点(S_设备环境& ctx) : C_节点基类(DEF_累计计算节点) {
	m_Ctx = ctx;
	f_setWName(u"累计计算");

	C_插座基类* socket;
	DEF_创建F32_1D插座_I(u"源", nullptr);
	DEF_创建F32_1D插座_O(u"结果", nullptr);

	m_计算方式 = f_alloc_EnumProp(nullptr, {
			//	0			1					
			{u"+", u""}, {u"-", u""},
			//	2			3
			{u"*", u""}, {u"/", u""},
		},
		u"计算方式",
		0,
		nullptr
	);
	m_计算方式.m_私有 = true;


	m_累积方式 = f_alloc_EnumProp(nullptr, {
		//	0			1					
		{u"逐个", u""}, 
		{u"合并", u""},
	}, u"计算方式");
	m_累积方式.m_私有 = true;
}

C_累计计算节点::~C_累计计算节点() {
	f_prop_Release(m_计算方式);
	f_prop_Release(m_累积方式);
}

bool C_累计计算节点::f_update() {
	//auto& v = DEF_F32插座数据(f_get输入插座(1));
	//auto& r = DEF_F32插座数据(f_get输出插座(1));

	return false;
}

std::string C_累计计算节点::DEF_节点编译函数{
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();

	auto* socket1 = f_get输入插座(1);
	
	switch (f_prop_enum(m_累积方式)) {
		case 0: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);
			m_Code = DEF_S(S_F32Array*)" " + name + " = " + f_代码构建_创建数组(E_值类型::e_Type_F32_1D, 1) + ";\n";


			m_Code += "{\n";
			m_Code += socket1->f_构建变量代码(0);
			m_Code += DEF_S(f_JIT_单值累计计算)"(" + name + ", " + socket1->f_getCode(0) + ", " + f_代码构建_属性变量(m_计算方式, f_getThis节点树()) + ");\n";
			break;
		}
		case 1: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
			m_Code = DEF_S(float32)" " + name + ";\n";


			m_Code += "{\n";
			m_Code += socket1->f_构建变量代码(0);
			m_Code += name + " = ";
			m_Code += DEF_S(f_JIT_单值合并计算)"(" + socket1->f_getCode(0) + ", " + f_代码构建_属性变量(m_计算方式, f_getThis节点树()) + ");\n";
			break;
		}
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		switch (f_prop_enum(m_累积方式)) {
			case 0: {
				m_区域父节点->m_ReleaseCode.insert(0, f_代码构建_销毁数组(name));
				break;
			}
		}
		return "";
	}
	switch (f_prop_enum(m_累积方式)) {
		case 0: {
			释放 += f_代码构建_销毁数组(name);
			break;
		}
	}
	
	return m_Code;
}


void C_累计计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_累积方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_累计计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);
	f_prop_Save(m_累积方式, 块);

	f_file_保存文件块(f, 文件块, 块);
}

void C_累计计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);

	auto 节点 = dynamic_cast<const C_累计计算节点*>(node);
	if (节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(节点->m_计算方式);
		f_prop_enum(m_累积方式) = f_prop_enum(节点->m_累积方式);
	}
}

C_节点基类* f_node_创建累计计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_累计计算节点(ctx);
}

C_节点基类* f_node_加载累计计算节点(S_设备环境& ctx, FILE* f) {
	C_累计计算节点* node = new C_累计计算节点(ctx);
	return node;
}

void f_node_保存累计计算节点(C_节点基类* n, FILE* f) {
	C_累计计算节点* node = dynamic_cast<C_累计计算节点*>(n);
}





